package vno.fux
{
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	/**
	 * 显示对象的基类
	 * 继承自Sprite，实现了注册点的设置
	 * 注册点解释：图像在移动，放大，旋转等操作时的原点（中心点）
	 * 
	 * 此类的实例应该仅持有一个显示内容，由content指定
	 * 请不要使用父类对Child操作的方法，如addChild等
	 * 调用这些方法会引发ArgumentError异常
	 * */
	/*======效率信息(n=10W,T:ms,i7-2600K@3.4GHz|12%)======
	空构造：514.18
	空构造后content=：731.05
	含content参构造：688.75
	含regSet参构造：534.8
	含regSet参构造后content=：935.15
	含双参构造：875
	=====================*/
	public class BaseDisplayObject extends Sprite
	{
		private var _regPoint:BasePoint = new BasePoint(0,0);//注册点坐标，相对于左上角
		private var _regPos:String = null;//注册位置，当手动设置注册点时，此值失效
		private var dispContent:DisplayObject = null;//显示内容
		private var _regable:Boolean = false;
		/**
		 *创建BaseDiplayObject对象，并设置注册点，注册位置，内容
		 * @param content 显示对象内容设置，其内容应该是一个可以被装载在DisplayObjectContainer内的对象（DisplayObject）
		 * @param regSet 显示对象注册点的设置，可接受注册位置信息（RegPos:String）或者实际的点坐标
		 * 注册位置解释：注册位置提供了一个相对的注册概念，例如注册点处在图像的中心，亦或是左上角。
		 * */
		public function BaseDisplayObject(content_:DisplayObject = null,regSet:* = null)
		{
			if(!regSet)
			{
			}
			else if(regSet is String)
			{
				_regable = true;
				_regPos = regSet;
			}
			else if(regSet is BasePoint)//传入点对象的情况
			{
				_regable = true;
				_regPoint.x = -regSet.x;
				_regPoint.y = -regSet.y;
			}
			else if(regSet is Array)//传入数组形式坐标的情况
			{
				_regable = true;
				_regPoint.x = -regSet[0];
				_regPoint.y = -regSet[1];
			}
			else if(regSet != null)//参数错误
			{
				throw new Error("Wrong regpoint type!");
			}
			if(content_)//若有内容，则将其加入显示列表
			{
				dispContent = content_;//加载内容
				super.addChild(dispContent);
				if(_regable)
				{
					refreshRegPoint();//根据新添的内容刷新注册点
				}
			}
			
		}
		
		/**
		 *注册点设置函数，接受点，数组，注册位置（字符串）类型的设置参数
		 * */
		public function setRegPoint(regp:*):void
		{
			if(regp is BasePoint)//传入点对象的情况
			{
				_regable = true;
				_regPoint.x = -(regp as BasePoint).x;
				_regPoint.y = -(regp as BasePoint).y;
			}
			else if(regp is Array)//传入数组形式坐标的情况
			{
				_regable = true;
				_regPos = null;
				_regPoint.x = -(regp as Array)[0];
				_regPoint.y = -(regp as Array)[1];
			}
			else if(regp is String)//传入注册位置的情况
			{
				_regable = true;
				_regPos = regp as String;
				convPos2Point();//根据注册位置刷新注册点
			}
			else if(!regp)
			{
				_regable = false;
			}
			else
			{
				throw new Error("setregPoint need only BasePoint、String、Array or Null(for disregable)");
			}
			if(_regable)
			{
				refreshRegPoint();
			}
		}
		
		/**
		 *根据注册位置转换出实际注册点 
		 * */
		private function convPos2Point():void
		{
			if(_regPos==null || !dispContent)//若注册位置为空或内容为零则直接返回
			{
				return;
			}
			switch(_regPos)//根据注册位置的值，由内容的高和宽计算出相应的注册点
			{
				case CompassDirection.NW:
					_regPoint.x = 0;
					_regPoint.y = 0;
					break;
				case CompassDirection.N:
					_regPoint.x = -dispContent.width/2;
					_regPoint.y = 0;
					break;
				case CompassDirection.NE:
					_regPoint.x = -dispContent.width;
					_regPoint.y = 0;
					break;
				case CompassDirection.E:
					_regPoint.x = -dispContent.width;
					_regPoint.y = -dispContent.height/2;
					break;
				case CompassDirection.SE:
					_regPoint.x = -dispContent.width;
					_regPoint.y = -dispContent.height;
					break;
				case CompassDirection.S:
					_regPoint.x = -dispContent.width/2;
					_regPoint.y = -dispContent.height;
					break;
				case CompassDirection.SW:
					_regPoint.x = 0;
					_regPoint.y = -dispContent.height;
					break;
				case CompassDirection.W:
					_regPoint.x = 0;
					_regPoint.y = -dispContent.height/2;
					break;
				case CompassDirection.CENTER:
					_regPoint.x = -dispContent.width/2;
					_regPoint.y = -dispContent.height/2;
					break;
			}
		}
		
		/**
		 *清空内容
		 * */
		protected function clear():void
		{
			if(dispContent)
			{
				super.removeChild(dispContent);
				dispContent = null;
			}
		}
		
		/**
		 *根据现有内容和设置，刷新注册点
		 * */	
		protected function refreshRegPoint():void
		{
			convPos2Point();
			if(dispContent)
			{
				dispContent.x = _regPoint.x;
				dispContent.y = _regPoint.y;
			}
		}
		
		
		public function get ox():Number
		{
			return -_regPoint.x;
		}
		public function get oy():Number
		{
			return -_regPoint.y;
		}
		
		public function get content():DisplayObject
		{
			return dispContent;
		}
		
		public function set content(value:DisplayObject):void
		{
			clear();
			dispContent = value;
			if(dispContent)
			{
				super.addChild(dispContent);
				if(_regable)
				{
					refreshRegPoint();
				}
			}
		}
		override public function set width(value:Number):void
		{
			this.dispContent.width = value;
			refreshRegPoint();
		}
		override public function set height(value:Number):void
		{
			this.dispContent.height = value;
			refreshRegPoint();
		}
		/**
		 * 重写addChild方法，调用此方法会引发ArgumentError异常
		 * 如需添加显示内容，请使用content属性
		 * */
		override public function addChild(child:DisplayObject):DisplayObject
		{
			throw new ArgumentError("Can't invoke the method 'addChild' for class 'BaseDisplayObject'，please use the property 'content'");
		}
		/**
		 * 重写addChildAt方法，调用此方法会引发ArgumentError异常
		 * 对显示内容的操作，请使用content属性
		 * */
		override public function addChildAt(child:DisplayObject, index:int):DisplayObject
		{
			throw new ArgumentError("Can't invoke the method 'addChildAt' for class 'BaseDisplayObject'，please use the property 'content'");
		}
//		/**
//		 * 重写getChildAt方法，调用此方法会引发ArgumentError异常
//		 * 对显示内容的操作，请使用content属性
//		 * */
//		override public function getChildAt(index:int):DisplayObject
//		{
//			throw new ArgumentError("Can't invoke the method 'getChildAt' for class 'BaseDisplayObject'，please use the property 'content'");
//		}
		/**
		 * 重写getChildByName方法，调用此方法会引发ArgumentError异常
		 * 对显示内容的操作，请使用content属性
		 * */
		override public function getChildByName(name:String):DisplayObject
		{
			throw new ArgumentError("Can't invoke the method 'getChildByName' for class 'BaseDisplayObject'，please use the property 'content'");
		}
		/**
		 * 重写getChildIndex方法，调用此方法会引发ArgumentError异常
		 * 对显示内容的操作，请使用content属性
		 * */
		override public function getChildIndex(child:DisplayObject):int
		{
			throw new ArgumentError("Can't invoke the method 'getChildIndex' for class 'BaseDisplayObject'，please use the property 'content'");
		}
		/**
		 * 重写removeChild方法，调用此方法会引发ArgumentError异常
		 * 对显示内容的操作，请使用content属性
		 * */
		override public function removeChild(child:DisplayObject):DisplayObject
		{
			throw new ArgumentError("Can't invoke the method 'removeChild' for class 'BaseDisplayObject'，please use the property 'content'");
		}
		/**
		 * 重写removeChildAt方法，调用此方法会引发ArgumentError异常
		 * 对显示内容的操作，请使用content属性
		 * */
		override public function removeChildAt(index:int):DisplayObject
		{
			throw new ArgumentError("Can't invoke the method 'removeChildAt' for class 'BaseDisplayObject'，please use the property 'content'");
		}
		/**
		 * 重写setChildIndex方法，调用此方法会引发ArgumentError异常
		 * 对显示内容的操作，请使用content属性
		 * */
		override public function setChildIndex(child:DisplayObject, index:int):void
		{
			throw new ArgumentError("Can't invoke the method 'setChildIndex' for class 'BaseDisplayObject'，please use the property 'content'");
		}
		/**
		 * 重写swapChildren方法，调用此方法会引发ArgumentError异常
		 * 对显示内容的操作，请使用content属性
		 * */
		override public function swapChildren(child1:DisplayObject, child2:DisplayObject):void
		{
			throw new ArgumentError("Can't invoke the method 'swapChildren' for class 'BaseDisplayObject'，please use the property 'content'");
		}
		/**
		 * 重写swapChildrenAt方法，调用此方法会引发ArgumentError异常
		 * 对显示内容的操作，请使用content属性
		 * */
		override public function swapChildrenAt(index1:int, index2:int):void
		{
			throw new ArgumentError("Can't invoke the method 'swapChildrenAt' for class 'BaseDisplayObject'，please use the property 'content'");
		}
		
	}
}